// MX710Lights.cpp: implementation of the CMX710Lights class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "MXLights.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif









//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMX610Lights::CMX610Lights()
{
	m_IsTurnOffLedsOnExit=true;
	m_MyDeviceDetected = false; 
	m_WriteHandle=NULL;	
	m_DeviceHandle=NULL;
	m_detailData = NULL;
	Clear();

}






CMX610Lights::~CMX610Lights()
{

	if (m_IsTurnOffLedsOnExit)
	{
		Control(  MX610_MESSENGER_INSTANTOFF );
		Sleep(100);
		Control(  MX610_MAIL_INSTANTOFF );
		Sleep(100);
	}
	Close();
	
}

bool CMX610Lights::Open()
{


	return FindTheHID();

}


void CMX610Lights::Clear()
{
	m_MyDeviceDetected = false; 

	if (m_DeviceHandle != INVALID_HANDLE_VALUE) 	CloseHandle(m_DeviceHandle);
	m_DeviceHandle=NULL;
	if (m_WriteHandle != INVALID_HANDLE_VALUE)		CloseHandle(m_WriteHandle);
	m_WriteHandle=NULL;

	ZeroMemory(&m_Capabilities,sizeof(HIDP_CAPS));

	if (m_detailData!=NULL) free(m_detailData);
	m_detailData=NULL;
	m_Length=0;
	m_Required=0;

}



void CMX610Lights::Close()
{

	if (!m_MyDeviceDetected) return;








	Clear();

}

bool CMX610Lights::FindTheHID()
{

	if (m_MyDeviceDetected) return true;

	Clear();

	SP_DEVICE_INTERFACE_DATA			devInfoData;
	int									MemberIndex = 0;
	bool								LastDevice = FALSE;
	LONG								Result;	
	HIDD_ATTRIBUTES						Attributes;



	HidD_GetHidGuid(&m_HidGuid);	

	
	m_hDevInfo=SetupDiGetClassDevs 
		(	&m_HidGuid, 
			NULL, 
			NULL, 
			DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
		
	devInfoData.cbSize = sizeof(devInfoData);

	MemberIndex = 0;




	do
	{

		Result=SetupDiEnumDeviceInterfaces 
				(	m_hDevInfo, 
					0, 
					&m_HidGuid, 
					MemberIndex, 
					&devInfoData
				);


		if (Result==0) break;


		Result = SetupDiGetDeviceInterfaceDetail 
					(	m_hDevInfo, 
						&devInfoData, 
						NULL, 
						0, 
						&m_Length, 
						NULL
					);
		m_detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(m_Length);
		m_detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		Result = SetupDiGetDeviceInterfaceDetail 
					(	m_hDevInfo, 
						&devInfoData, 
						m_detailData, 
						m_Length, 
						&m_Required, 
						NULL
					);

		m_DeviceHandle=CreateFile 
				(	m_detailData->DevicePath, 
					0, 
					FILE_SHARE_READ|FILE_SHARE_WRITE, 
					(LPSECURITY_ATTRIBUTES)NULL,
					OPEN_EXISTING, 
					0, 
					NULL
				);
		Attributes.Size = sizeof(Attributes);
		Result = HidD_GetAttributes 
				(	m_DeviceHandle, 
					&Attributes
				);


		if ((Attributes.VendorID == MX610_VID) &&  (Attributes.ProductID == MX610_PID))
		{
			GetDeviceCapabilities();

			if ((m_Capabilities.InputReportByteLength==MX610_IRBL) && (m_Capabilities.OutputReportByteLength==MX610_ORBL))
			{
				// GOT IT !!!

				m_MyDeviceDetected=true;

				m_WriteHandle=CreateFile 
					(	m_detailData->DevicePath, 
						GENERIC_WRITE, 
						FILE_SHARE_READ|FILE_SHARE_WRITE, 
						(LPSECURITY_ATTRIBUTES)NULL,
						OPEN_EXISTING, 
						0, 
						NULL
					);
	
				break;
				
			}



		}

		CloseHandle(m_DeviceHandle);
		m_DeviceHandle=NULL;
		free(m_detailData);
		m_detailData=NULL;
		MemberIndex++;

	} while (1);

	if (!m_MyDeviceDetected) Clear();

	return m_MyDeviceDetected;
}







bool CMX610Lights::Control(int type)
{
	static unsigned char R[20][MX610_ORBL] = 
	{
		{ 0x10, 0x01, 0x80, 0x52, 0x06, 0x00, 0x00 },//MX610_MAIL_OFF	
		{ 0x10, 0x01, 0x80, 0x52, 0x05, 0x00, 0x00 },//MX610_MAIL_ON
		{ 0x10, 0x01, 0x80, 0x52, 0x04, 0x00, 0x00 },//MX610_MAIL_PULSE
		{ 0x10, 0x01, 0x80, 0x52, 0x03, 0x00, 0x00 },//MX610_MAIL_FLASH
		{ 0x10, 0x01, 0x80, 0x52, 0x02, 0x00, 0x00 },//MX610_MAIL_INSTANTON
		{ 0x10, 0x01, 0x80, 0x52, 0x01, 0x00, 0x00 },//MX610_MAIL_INSTANTOFF

		{ 0x10, 0x01, 0x80, 0x52, 0x00, 0x06, 0x00 },//MX610_MESSENGER_OFF
		{ 0x10, 0x01, 0x80, 0x52, 0x00, 0x05, 0x00 },//MX610_MESSENGER_ON
		{ 0x10, 0x01, 0x80, 0x52, 0x00, 0x04, 0x00 },//MX610_MESSENGER_PULSE
		{ 0x10, 0x01, 0x80, 0x52, 0x00, 0x03, 0x00 },//MX610_MESSENGER_FLASH
		{ 0x10, 0x01, 0x80, 0x52, 0x00, 0x02, 0x00 },//MX610_MESSENGER_INSTANTON
		{ 0x10, 0x01, 0x80, 0x52, 0x00, 0x01, 0x00 },//MX610_MESSENGER_INSTANTOFF

	};

	if (!m_MyDeviceDetected) return false;
	if ((type<0)||(type>MX610_LIGHTMAX)) return false;

	memcpy(m_OutputReport,R[type],MX610_ORBL);
	WriteOutputReport();

	return true;

}

void CMX610Lights::GetDeviceCapabilities()
{
	if (m_DeviceHandle==NULL) 
	{	
		ZeroMemory(&m_Capabilities,sizeof(HIDP_CAPS));
		return;
	}

	PHIDP_PREPARSED_DATA	PreparsedData;
	HidD_GetPreparsedData(m_DeviceHandle, &PreparsedData);
	HidP_GetCaps(PreparsedData, &m_Capabilities);
	HidD_FreePreparsedData(PreparsedData);

}



bool CMX610Lights::WriteOutputReport()
{

	if (m_WriteHandle == INVALID_HANDLE_VALUE) return false;

	DWORD	BytesWritten = 0;
	INT		Index =0;
	ULONG	Result;
	CString	strBytesWritten = "";
	
	Result = WriteFile 
		(	m_WriteHandle, 
			m_OutputReport, 
			m_Capabilities.OutputReportByteLength, 
			&BytesWritten, 
			NULL
		);
	

	if (!Result)
	{
			Clear();
			return false;
	} 

	return true;

}


void CMX610Lights::TurnOffLedsOnExit(bool isTurnOff)
{
	m_IsTurnOffLedsOnExit=isTurnOff;
}
